// @ts-nocheck
//设置不检查TypeScript类型
import { sendEvent } from "./vscode";

Draw.loadPlugin(function (ui: any) {
    if (ui.editor.isChromelessView()) {
        return;
    }

    //const vscode = acquireVsCodeApi();
    //console.log(vscode);
    var c = ui.sidebar.container;
    var general = c.getElementsByTagName('a')[0];
    general.click();

    var graph = ui.editor.graph;
    var model = graph.getModel();
    var autoIncrementId = 1;//自增ID

    const importActionName = "vscode.import";
    const exportActionName = "vscode.export";
    mxResources.parse(`${importActionName}=导入...`);
    mxResources.parse(`${exportActionName}=导出...`);

    ui.actions.addAction(importActionName, () => {
        var input = document.createElement('input');
        input.setAttribute('type', 'file');
        input.style.display = 'none';

        input.onchange = function () {
            if (input.files != null) {
                // Only one file for now...
                var reader = new FileReader();

                reader.onload = function (e) {
                    //console.log(e.target.result);
                    try {
                        createSideBar(JSON.parse(e.target.result));
                    } catch (ex) {
                        ui.showTextDialog('数据错误', '只支持导入IR文件！\n' + e.target.result);
                    }
                };

                reader.readAsText(input.files[0]);

                // Resets input to force change event for same file (type reset required for IE)
                input.type = '';
                input.type = 'file';
                input.value = '';
            }
        };
        document.body.appendChild(input);
        input.click();
    });
    ui.actions.addAction(exportActionName, () => {
        sendEvent({ event: "invokeCommand", command: "export" });
    });
    const menu = ui.menus.get("file");
    const oldFunct = menu.funct;
    menu.funct = function (menu: any, parent: any) {
        oldFunct.apply(this, arguments);
        ui.menus.addMenuItems(
            menu,
            [
                "-",
                importActionName,
                exportActionName
            ],
            parent
        );
    };
    //添加cell后触发回调
    graph.addListener(mxEvent.CELLS_ADDED, function (sender: any, evt: any) {
        // console.log(sender)
        // console.log(evt)
        var cells = evt.getProperty('cells');
        console.log(Array.isArray(cells))
        cells.forEach((cell) => {
            if (!cell.cType) {//不是CDL的实体，直接返回
                return;
            }
            let suffix = cell.value.charAt(cell.value.length - 1);//获得cdl实体名称最后一个字符
            if (suffix <= '0' || suffix >= '9') {//是数字的话表明已经重命名过了
                cell.value += autoIncrementId++;//否则需要加一个自增的id
            }
        })
    });
    //连接边后触发回调
    graph.addListener(mxEvent.CELL_CONNECTED, function (sender, evt) {
        var edge = evt.getProperty('edge');
        if (!edge.source || !edge.target) {//边没有连接上两个实体,无需继续判断
            return;
        }
        if (edge.source.cType !== 'interface' && edge.target.cType !== 'interface') {
            graph.removeCells([edge]);//不通过的话要移除刚才添加的边
            ui.showTextDialog('连线错误', '不允许非接口类型的实体之间连线！');
            return;
        }
        if (edge.source.cInterfaceModifier !== 'provide' || edge.target.cInterfaceModifier !== 'require') {
            graph.removeCells([edge]);//不通过的话要移除刚才添加的边
            ui.showTextDialog('连线错误', '只允许从provide接口向require接口连线！');
            return;
        }
        if (edge.source.cInterfaceType !== edge.target.cInterfaceType) {
            graph.removeCells([edge]);//不通过的话要移除刚才添加的边
            //ui.showAlert('只允许从provide接口向require接口连线！');
            ui.showTextDialog('连线错误', '接口的数据类型必须一致！');
            return;
        }
        console.log('边连接检查通过');
        //把两边的接口的服务名改成一样的
        edge.source.cServiceName = edge.source.cInterfaceName + edge.source.id;
        edge.target.cServiceName = edge.source.cServiceName;
    });
    // Reusable cells
    //字段
    var field = new mxCell('+ field: type', new mxGeometry(0, 0, 100, 26), 'text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;');
    field.vertex = true;
    //分隔符
    var divider = new mxCell('', new mxGeometry(0, 0, 40, 8), 'line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;');
    divider.vertex = true;

    // Adds sidebar entries
    //侧边栏
    var sb = ui.sidebar;
    console.log(Object.keys(sb));

    //创建结构体cell
    function createStructureNode(structureEntity) {
        var cell = new mxCell(structureEntity.name, new mxGeometry(0, 0, 160, 90),
            'swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;');
        cell.vertex = true;
        structureEntity.members.forEach((member, index) => {
            // cell.insert(sb.cloneCell(field, '+ method(type): type'));
            cell.insert(sb.cloneCell(field, `+ ${member.name}: ${member.type.typeName}`));
            if (index < structureEntity.members.length - 1) {
                cell.insert(divider.clone());//最后一条后面不加分割线
            }
        })

        return sb.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, 'Component')
    }
    //创建端口cell
    function createPortNode(portEntity) {
        var cell = new mxCell('<p style="margin:0px;margin-top:4px;text-align:center;">' +
            `<b>${portEntity.name}</b></p>` +
            `<hr size="1"/><div style="height:2px;">${portEntity.desc.desc.name}</div>`, new mxGeometry(0, 0, 140, 60),
            'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;');
        cell.vertex = true;
        cell.cType = 'single-port';

        return sb.createVertexTemplateFromCells([cell.clone()], cell.geometry.width, cell.geometry.height, 'Port');
    }
    //创建接口cell
    function createInterfaceNode(interfaceEntity) {
        var cell = new mxCell(interfaceEntity.name, new mxGeometry(0, 0, 160, 90),
            'swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;');
        cell.vertex = true;
        cell.cType = 'single-interface';
        interfaceEntity.operations.forEach((operation, index) => {//遍历接口中的函数
            let parameterList = [];
            operation.parameters.forEach((parameter) => {//遍历该函数的参数列表
                parameterList.push(`${parameter.direction} ${parameter.type.typeName}`)
            });
            cell.insert(sb.cloneCell(field, `+ ${operation.name}(${parameterList.join(',')}): ${operation.returnType.typeName}`));//拼接参数和返回值
            if (index < interfaceEntity.operations.length - 1) {
                cell.insert(divider.clone());//最后一条后面不加分割线
            }
        })

        return sb.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, 'Interface');
    }
    //创建应用容器
    function createApplicationNode() {
        var cell = new mxCell('Application', new mxGeometry(0, 0, 200, 200),
            'swimlane;align=center;childLayout=stackLayout;horizontal=1;horizontalStack=0;');
        cell.vertex = true;
        cell.cType = 'application';
        return sb.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, 'Container')
    }
    //创建组件里的端口的cell
    function createComponentPortNode(componentEntity) {
        var portCells = [];
        for (let i = 0; i < componentEntity.ports.length; i++) {
            const port = componentEntity.ports[i];
            const label = `${port.modifier} ${port.entity.name} ${port.name}`;
            let cell = new mxCell(label, new mxGeometry(0, 0, 100, 26), 'text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;');
            cell.vertex = true;
            cell.cType = 'port';//标识该cell是一个端口
            cell.cPortType = port.entity.name;
            cell.cPortName = port.name;
            cell.cPortModifier = port.modifier;
            //cell.cRawBase64 = Base64.encode(JSON.stringify(port));//把原始数据序列化为base64，备用
            portCells.push(cell);
        }
        return portCells;
    }
    //创建组件里的接口的cell
    function createComponentInterfaceNode(componentEntity) {
        var interfaceCells = [];
        for (let i = 0; i < componentEntity.interfaces.length; i++) {
            const theInterface = componentEntity.interfaces[i];
            const label = `${theInterface.modifier} ${theInterface.entity.name} ${theInterface.name}`;
            let cell = new mxCell(label, new mxGeometry(0, 0, 100, 26), 'text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;');
            cell.vertex = true;
            cell.cType = 'interface';
            cell.cInterfaceModifier = theInterface.modifier;
            cell.cServiceName = 'defaultServiceName';//这里有一个默认值，连线时把serviceName改成一样的
            cell.cInterfaceType = theInterface.entity.name;
            cell.cInterfaceName = theInterface.name;
            //cell.cRawBase64 = Base64.encode(JSON.stringify(interface));
            interfaceCells.push(cell);
        }
        return interfaceCells;
    }
    //创建组件Cell
    function createComponentNode(element) {
        var cell = new mxCell(element.name, new mxGeometry(0, 0, 160, 90),
            'swimlane;0;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;');
        cell.vertex = true;
        cell.cType = 'component';
        cell.cComponentType = element.name;
        cell.cHasUi = element.isUIComponent;
        //cell.cRawBase64 = Base64.encode(JSON.stringify(element));
        let portCells = createComponentPortNode(element);
        console.log(portCells);
        for (let i = 0; i < portCells.length; i++) {
            cell.insert(portCells[i]);
        }
        cell.insert(divider.clone());
        let interfaceCells = createComponentInterfaceNode(element);
        for (let i = 0; i < interfaceCells.length; i++) {
            cell.insert(interfaceCells[i]);
        }
        return sb.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, element.isUIComponent ? 'UI Component' : 'Service Component')
    }
    function createSideBar(rawData) {
        //添加到侧边栏
        sb.addPalette('cdl-complex', '数据类型', true, function (content) {
            rawData.entities.filter((entity) => {
                return entity.type == 2;
            }).forEach((entity) => {
                content.appendChild(createStructureNode(entity));
            });
        });

        sb.addPalette('cdl-interfacePort', '接口和端口', true, function (content) {
            rawData.entities.filter((entity) => {
                return entity.type == 4;
            }).forEach((entity) => {
                content.appendChild(createPortNode(entity));
            });
            rawData.entities.filter((entity) => {
                return entity.type == 5;
            }).forEach((entity) => {
                content.appendChild(createInterfaceNode(entity));
            });
        });
        sb.addPalette('cdl-component', '组件和容器', true, function (content) {
            content.appendChild(createApplicationNode());
            rawData.entities.filter((entity) => {
                return entity.type == 7;
            }).forEach((entity) => {
                content.appendChild(createComponentNode(entity));
            });
        });

        // Collapses default sidebar entry and inserts this before
        //把新加的Palette移到前面
        var c = ui.sidebar.container;
        var general = c.getElementsByTagName('a')[0];
        general.click();

        for (let i = 0; i < 3; i++) {
            c.insertBefore(c.lastChild.previousSibling, general);
            c.insertBefore(c.lastChild, general);
        }
    }

});